package com.sonic.jms.utils.xmlmapper;

import java.io.InputStreamReader;

import javax.ejb.EJBException;

import org.castor.mapping.BindingType;
import org.exolab.castor.xml.ClassDescriptorResolverFactory;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.ResolverException;
import org.exolab.castor.xml.Unmarshaller;
import org.exolab.castor.xml.ValidationException;
import org.exolab.castor.xml.XMLClassDescriptorResolver;
import org.exolab.castor.xml.XMLContext;

import com.sonic.jms.exceptions.MQuotesMapperException;
import com.sonic.log.ejb.impl.MQLogger;
import com.sonic.mquotes.dto.ElementType;
import com.sonic.mquotes.dto.Elements;
import com.sonic.mquotes.dto.MarketInfoSE;
import com.sonic.mquotes.dto.MarketInfoTypeSE;
import com.sonic.mquotes.dto.MqMarketInfoMessageSE;
import com.sonic.mquotes.dto.MqPapMessage;
import com.sonic.mquotes.dto.MqQuoteMessage;
import com.sonic.mquotes.dto.OfferLineData;
import com.sonic.mquotes.dto.OfferLineType;
import com.sonic.mquotes.dto.OfferLineTypeBody;
import com.sonic.mquotes.dto.OfferLines;


/** 
 * MQCastorXmlMapper class.<br>
 * Maps XML to object.
 * 
 * @author <b>Adam Dec</b> for <b><I>iBroker</i></b><br> Copyright &#169; 2008/2009
 * @since 29-12-2008
 * @category BROKER XML MAPPER
 * @version 1.0
 */
public class MQCastorXmlMapper {
	public static MQLogger logger       = new MQLogger(MQCastorXmlMapper.class, "MQ-XML-MAPPER");
	private static MQCastorXmlMapper instance;
	private static Unmarshaller unmarshaller;
	private static XMLContext context;	
	
	private static final Class<?>[] clazzes = {
		ElementType.class,
		MqPapMessage.class,
		Elements.class,
		MqMarketInfoMessageSE.class,
		OfferLineTypeBody.class,
		MarketInfoSE.class,
		OfferLines.class,
		OfferLineData.class,
		MarketInfoTypeSE.class,
		MqQuoteMessage.class,
		OfferLineType.class
	};
	
	static {
		context 	 = new XMLContext();  
		unmarshaller = context.createUnmarshaller();
		
		XMLClassDescriptorResolver classDescriptorResolver = (XMLClassDescriptorResolver) ClassDescriptorResolverFactory.createClassDescriptorResolver(BindingType.XML);
		if(classDescriptorResolver == null) {
			logger.debug("static", " --- [ERROR] MQCastorXmlMapper, XMLClassDescriptorResolver has not been created!");
        	throw new EJBException("MQCastorXmlMapper, XMLClassDescriptorResolver has not been created!");
		}
			
		try {
			classDescriptorResolver.setUseIntrospection(false);	
	        classDescriptorResolver.addClasses(clazzes);
        } catch (ResolverException e) {
        	logger.debug("static", " --- [ERROR] MQCastorXmlMapper, XMLClassDescriptorResolver has not been created!");
        	logger.error("static", e.getErrorCode(), e.getMessage());
        	throw new EJBException(e);
        } catch (Exception e) {
        	logger.debug("static", " --- [ERROR] MQCastorXmlMapper, XMLClassDescriptorResolver has not been created!");
        	logger.debug("static", e.getMessage());
        	System.out.println(e);
        	throw new EJBException(e);
        }
		unmarshaller.setResolver(classDescriptorResolver);
		unmarshaller.setValidation(false);
	}
	
	private MQCastorXmlMapper() { }
	
	public static MQCastorXmlMapper getInstance() {
		return instance != null ? instance : new MQCastorXmlMapper();
	}

	public static final Object mapXmlToObject(final InputStreamReader reader) throws MQuotesMapperException {
		final String methodName = "mapXmlToObject";
		try {
	        return unmarshaller.unmarshal(reader);
        } catch (MarshalException e) {
        	logger.debug(methodName, " --- [ERROR] MQCastorXmlMapper, xml has not been unmarshalled!");
        	logger.error(methodName, e.getErrorCode(), e.getMessage());        	
	        throw new MQuotesMapperException(e);
        } catch (ValidationException e) {
        	logger.debug(methodName, " --- [ERROR] MQCastorXmlMapper, xml validation exception appeared!");
        	logger.error(methodName, e.getErrorCode(), e.getMessage());  
        	throw new MQuotesMapperException(e);
        }		
	}
	
	@Override
    protected Object clone() throws CloneNotSupportedException {
		throw new CloneNotSupportedException();
    }	
}